package com.xq.sqlSession;

import com.xq.pojo.Configuration;
import com.xq.pojo.MappedStatement;
import com.xq.util.GenericTokenParser;
import com.xq.util.ParameterMapping;
import com.xq.util.ParameterMappingTokenHandler;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

public class BaseExecutor {
    public PreparedStatement getPreparedStatement(Configuration configuration, MappedStatement mappedStatement, Object... params) throws Exception {
        //构建连接
        Connection connection = configuration.getDataSource().getConnection();
        //获取sql select * from user where id=#{id} and username=#{username}
        String sql = mappedStatement.getSql();
        //构建boundSql 获取解析后的sql 还有解析的参数{id ,username}
        BoundSql boundSql=getBoundSql(sql);
        //预处理sql select * from user where id=? and username=?
        String paresSql = boundSql.getParesSql();
        PreparedStatement preparedStatement = connection.prepareStatement(paresSql);
        //获取参数类型parameterType对应实体类
        String parameterType = mappedStatement.getParameterType();
        Class<?> classType=getClassType(parameterType);

        //设置参数
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        for (int i=0;i<parameterMappings.size();i++) {
            ParameterMapping parameterMapping = parameterMappings.get(i);
            //获取内容为id username 对应为实体user属性，然后获取对应属性的值
            String content = parameterMapping.getContent();
            Field declaredField = classType.getDeclaredField(content);
            declaredField.setAccessible(true);
            //这儿是因为传递参数类型和mapper.xml中的parameterType是一致的
            Object value = declaredField.get(params[0]);
            preparedStatement.setObject(i + 1, value);
        }
        return preparedStatement;
    }

    private Class<?> getClassType(String parameterType) throws Exception {
        if (parameterType != null) {
            Class<?> aClass = Class.forName(parameterType);
            return aClass;
        } else {
            return null;
        }
    }

    private BoundSql getBoundSql(String sql) {
        ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
        GenericTokenParser genericTokenParser = new GenericTokenParser("#{","}",parameterMappingTokenHandler);
        String parseSql = genericTokenParser.parse(sql);
        List<ParameterMapping> parameterMappings = parameterMappingTokenHandler.getParameterMappings();

        return new BoundSql(parseSql,parameterMappings);
    }
}
